package com.basic.business.order.server;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.basic.business.common.utils.StringUtils;
import com.basic.business.order.domain.TOrdersDetail;
import com.basic.business.order.domain.TOrdersMain;
import com.basic.business.order.domain.TOrdersMerge;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 订单解析服务
 */
@Slf4j
@Component
public class ParseOrders {

    /**
     * 解析订单数据，将JSON格式的订单列表转换为Java对象列表。
     *
     * @param jsonResult 包含订单数据的JSON对象，其中应包含一个名为"list"的JSON数组。
     * @return 解析后的订单对象列表，如果"list"为空或不存在，则返回空列表。
     */
    public static List<TOrdersMain> init(JSONObject jsonResult) {
            // 从jsonResult中获取"list"数组，如果数组存在且不为空，则解析为订单列表，否则返回空列表
            return Optional.ofNullable(jsonResult.getJSONArray("list"))
                    .filter(array -> !array.isEmpty())
                    .map(ParseOrders::parseOrderList)
                    .orElseGet(Collections::emptyList);
    }

    /**
     * 将JSONArray解析为TOrdersMain对象的列表。
     *
     * 该方法通过遍历JSONArray中的每个JSON对象，将其解析为TOrdersMain对象，
     * 并过滤掉解析结果为null的对象，最终返回一个包含所有有效TOrdersMain对象的列表。
     *
     * @param jsonArray 包含订单信息的JSONArray，每个元素为一个JSON对象。
     * @return 返回一个包含所有有效TOrdersMain对象的列表，如果jsonArray为空或所有解析结果均为null，则返回空列表。
     */
    private static List<TOrdersMain> parseOrderList(JSONArray jsonArray) {
        // 使用IntStream遍历JSONArray中的每个索引，将每个JSON对象解析为TOrdersMain对象
        return IntStream.range(0, jsonArray.size())
                .mapToObj(index -> parseSingleOrder(jsonArray.getJSONObject(index)))
                .filter(Objects::nonNull) // 过滤掉解析结果为null的对象
                .collect(Collectors.toList()); // 将结果收集到List中
    }


    /**
     * 解析单个订单的JSON对象，并将其转换为TOrdersMain对象。
     * 该函数会处理订单的主信息、子订单、合并订单以及订单标签。
     *
     * @param orderJson 包含订单信息的JSON对象
     * @return 解析后的TOrdersMain对象，如果解析过程中发生异常则返回null
     */
    private static TOrdersMain parseSingleOrder(JSONObject orderJson) {
        try {
            // 将JSON对象转换为TOrdersMain对象
            TOrdersMain mainOrder = orderJson.toJavaObject(TOrdersMain.class);

            // 处理子订单信息
            processSubOrders(orderJson, mainOrder);

            // 处理合并订单信息
            processMergedOrders(orderJson, mainOrder);

            // 处理订单标签信息
            processOrderTags(orderJson, mainOrder);

            return mainOrder;
        } catch (Exception e) {
            // 记录解析异常日志，并返回null
            log.error("订单解析异常: {}", orderJson, e);
            return null;
        }
    }


    /**
     * 处理子订单信息，并将其与主订单关联。
     *
     * 该方法从传入的JSON对象中提取子订单信息，解析为订单详情列表，并将其设置到主订单中。
     * 如果只有一个子订单，则将主订单的卖家备注同步到该子订单中。
     *
     * @param orderJson 包含订单信息的JSON对象，其中可能包含子订单数组
     * @param mainOrder 主订单对象，用于关联子订单信息
     */
    private static void processSubOrders(JSONObject orderJson, TOrdersMain mainOrder) {
        // 从JSON对象中获取子订单数组，如果存在则进行处理
        Optional.ofNullable(orderJson.getJSONArray("orders"))
                .ifPresent(ordersArray -> {
                    // 解析子订单数组为订单详情列表，并与主订单关联
                    List<TOrdersDetail> details = parseOrderDetails(ordersArray, mainOrder.getSid());
                    mainOrder.setDetailList(details);
                });
    }


    /**
     * 解析订单详情信息，并将其转换为TOrdersDetail对象的列表。
     *
     * @param ordersArray 包含订单详情的JSON数组，每个元素是一个JSON对象，表示一个订单详情。
     * @param mainSid 主订单的唯一标识符，用于关联订单详情。
     * @return 返回一个TOrdersDetail对象的列表，包含所有解析成功的订单详情。如果某个订单详情解析失败，则不会包含在返回的列表中。
     */
    private static List<TOrdersDetail> parseOrderDetails(JSONArray ordersArray, Long mainSid) {
        // 使用IntStream遍历ordersArray中的每个元素，并将其转换为JSONObject
        return IntStream.range(0, ordersArray.size())
                .mapToObj(ordersArray::getJSONObject)
                // 将每个JSONObject转换为TOrdersDetail对象，并关联主订单的mainSid
                .map(detailJson -> createOrderDetail(detailJson, mainSid))
                // 过滤掉解析失败的订单详情（即返回null的对象）
                .filter(Objects::nonNull)
                // 将解析成功的订单详情收集到一个列表中
                .collect(Collectors.toList());
    }


    /**
     * 根据传入的JSON对象和主订单ID创建订单明细对象。
     *
     * @param detailJson 包含订单明细信息的JSON对象
     * @param mainSid 主订单ID，用于关联订单明细与主订单
     * @return 返回创建的订单明细对象
     */
    private static TOrdersDetail createOrderDetail(JSONObject detailJson, Long mainSid) {
        // 将JSON对象转换为TOrdersDetail对象，并设置主订单ID
        TOrdersDetail detail = detailJson.toJavaObject(TOrdersDetail.class);
        detail.setMainSid(mainSid);

        // 处理标题：如果JSON对象中存在非空的sysTitle字段，则将其设置为订单明细的标题
        Optional.ofNullable(detailJson.getString("sysTitle"))
                .filter(StringUtils::isNotEmpty)
                .ifPresent(detail::setTitle);

        // 标记赠品：如果JSON对象中的giftNum字段大于0，则标记该订单明细为赠品
        detail.setIsGift(detailJson.getInteger("giftNum") > 0 ? "Y" : "N");

        return detail;
    }


    /**
     * 处理合并订单信息，解析并应用卖家备注到主订单中。
     *
     * @param orderJson 包含订单信息的JSON对象，其中可能包含合并订单的备注信息。
     * @param mainOrder 主订单对象，用于存储解析后的合并订单信息。
     */
    private static void processMergedOrders(JSONObject orderJson, TOrdersMain mainOrder) {
        // 检查并解析订单中的备注信息
        Optional.ofNullable(orderJson.getJSONArray("messageMemos"))
                .ifPresent(memosArray -> {
                    // 解析合并订单信息，并将其设置到主订单中
                    List<TOrdersMerge> merges = parseMergedOrders(memosArray, mainOrder.getSid());
                    mainOrder.setMergeList(merges);
                });
        // 如果messageMemos为空，则是单一订单，将主订单的备注同步到合单表中
        if (mainOrder.getMergeList().isEmpty()) {
            // 获取主订单的卖家备注
            String sellerMemo = mainOrder.getSellerMemo();
            // 如果卖家备注不为空，则将其设置到主订单的合单备注中
            if (StringUtils.isNotEmpty(sellerMemo)) {
                TOrdersMerge merge = new TOrdersMerge();
                merge.setMergeSid(mainOrder.getSid());
                merge.setMainSid(mainOrder.getSid());
                merge.setTid(mainOrder.getTid());
                merge.setSysStatus(mainOrder.getSysStatus());
                merge.setIsMergeMain(1);
                merge.setSellerMemo(sellerMemo);
                mainOrder.setMergeList(Collections.singletonList(merge));
            }
        }

    }


    /**
     * 解析合并订单信息，将JSON数组转换为TOrdersMerge对象列表。
     *
     * @param memosArray 包含订单信息的JSON数组，每个元素为一个JSON对象。
     * @param mainSid 主订单的唯一标识符，将设置到每个TOrdersMerge对象中。
     * @return 返回一个包含解析后的TOrdersMerge对象的列表。
     */
    private static List<TOrdersMerge> parseMergedOrders(JSONArray memosArray, Long mainSid) {
        // 使用IntStream遍历JSON数组，将每个JSON对象转换为TOrdersMerge对象
        return IntStream.range(0, memosArray.size())
                .mapToObj(memosArray::getJSONObject)
                .map(memoJson -> {
                    // 将JSON对象转换为TOrdersMerge对象，并设置主订单的唯一标识符
                    TOrdersMerge merge = memoJson.toJavaObject(TOrdersMerge.class);
                    merge.setMainSid(mainSid);
                    return merge;
                })
                .collect(Collectors.toList()); // 将转换后的对象收集到列表中
    }


    /**
     * 处理订单标签信息，并将其设置到主订单对象中。
     *
     * 该函数从订单的JSON对象中提取标签信息，如果标签信息存在且不为空，则解析这些标签，
     * 并将其设置到主订单对象中。
     *
     * @param orderJson 包含订单信息的JSON对象，其中可能包含标签信息。
     * @param mainOrder 主订单对象，用于存储解析后的标签信息。
     */
    private static void processOrderTags(JSONObject orderJson, TOrdersMain mainOrder) {
        // 从orderJson中获取标签数组，如果存在且不为空，则解析并设置到mainOrder中
        Optional.ofNullable(orderJson.getJSONArray("tradeTags"))
                .filter(tagsArray -> !tagsArray.isEmpty())
                .map(ParseOrders::parseOrderTags)
                .ifPresent(mainOrder::setTags);
    }


    /**
     * 解析订单标签数组，并将标签ID拼接成逗号分隔的字符串。
     *
     * @param tagsArray 包含订单标签的JSON数组，每个标签是一个JSON对象，包含"id"字段。
     * @return 返回一个逗号分隔的字符串，包含所有非空的标签ID。如果标签ID为空或标签数组为空，则返回空字符串。
     */
    private static String parseOrderTags(JSONArray tagsArray) {
        // 使用IntStream遍历JSON数组中的每个元素，并将其转换为JSON对象
        return IntStream.range(0, tagsArray.size())
                // 将每个JSON对象映射为其"id"字段的值
                .mapToObj(tagsArray::getJSONObject)
                .map(tag -> tag.getString("id"))
                // 过滤掉空字符串的标签ID
                .filter(StringUtils::isNotEmpty)
                // 将所有非空的标签ID拼接成逗号分隔的字符串
                .collect(Collectors.joining(","));
    }

}